/////////////////////////////////////////////////////////////////////////////
/*/	
 *	Creator:		Joshua C. Rouzer
 *	Title:			
 *	Last Edited:	06/15/2013
 *	Summary:		
/*/
/////////////////////////////////////////////////////////////////////////////
#include "EventManager.h"

/////////////////////////////////////////////////////////////////////////////
// Function		: CEventManager
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
CEventManager::CEventManager(){

}
/////////////////////////////////////////////////////////////////////////////
// Function		: ~CEventManager
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
CEventManager::~CEventManager(){

}

/////////////////////////////////////////////////////////////////////////////
// Function		: GetInstance()
// Return		: CEventManager*
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
CEventManager* CEventManager::GetInstance(){
	static CEventManager instance;
	return &instance;
}
/////////////////////////////////////////////////////////////////////////////
// Function		: RegisterListener
// Parameters	: EventID - String that the listener must respond to.
//					Client - The Listener who respond to the EventID.
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CEventManager::RegisterListener(string EventID, CListener* Client){
	if( !Client || AlreadyRegistered(EventID, Client))
		return;

	m_Clients.insert(make_pair(EventID, Client));

}
/////////////////////////////////////////////////////////////////////////////
// Function		: UnregisterListener
// Parameters	: EventID - String that the listener must respond to.
//					Client - The Listener who respond to the EventID.
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CEventManager::UnregisterListener(string EventID, CListener* Client){
	pair<multimap<string, CListener*>::iterator, multimap<string, CListener*>::iterator> ClientRange;

	ClientRange = m_Clients.equal_range(EventID);

	multimap<string, CListener*>::iterator MapIter = ClientRange.first;

	for (MapIter; MapIter != ClientRange.second; MapIter++)
	{
		if ((*MapIter).second == Client)
		{
			MapIter = m_Clients.erase(MapIter);
			break;
		}
	}
}
/////////////////////////////////////////////////////////////////////////////
// Function		: UnregisterAllListeners
// Parameters	: Client - The Listeners to unregister.
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CEventManager::UnregisterAllListeners(CListener* Client){
	multimap<string, CListener*>::iterator MapIter = m_Clients.begin();

	while (MapIter != m_Clients.end())
	{
		if ((*MapIter).second == Client)
			MapIter = m_Clients.erase(MapIter);
		else
			MapIter++;
	}
}
/////////////////////////////////////////////////////////////////////////////
// Function		: AlreadyRegistered
// Parameters	: EventID - The Event to check for.
//			      Client - The listener to check for. 
// Return		: bool
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
bool CEventManager::AlreadyRegistered(string EventID, CListener* Client){
	bool Registered = false;

	pair<multimap<string, CListener*>::iterator, multimap<string, CListener*>::iterator> ClientRange;

	ClientRange = m_Clients.equal_range(EventID);

	multimap<string, CListener*>::iterator MapIter = ClientRange.first;

	for (MapIter; MapIter != ClientRange.second; MapIter++)
	{
		if ((*MapIter).second == Client)
		{
			Registered = true;
			break;
		}
	}

	return Registered;
}
/////////////////////////////////////////////////////////////////////////////
// Function		: CheckEventTriggered
// Parameters	: EventID - The Event you want to check for.
// Return		: bool
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
bool CEventManager::CheckEventTriggered(string EventID){
	list<Event>::iterator EventIter = m_CurrentEvents.begin();

	for (EventIter; EventIter != m_CurrentEvents.end(); EventIter++)
	{
		if ((*EventIter).GetEventIDtype() == EventID)
			return true;
	}

	return false;
}
/////////////////////////////////////////////////////////////////////////////
// Function		: SendEventNow
// Parameters	: EventID - The Event for listeners to react to.
//					Data - Any data needed to complete the event.
//					Listener - The listener to recieve the event.
//					Sender - The object who sent the event.
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CEventManager::SendEventNow(string EventID, void* Data, void* Listener, void* Sender){
	Event NewEvent(EventID, Data, Listener, Sender);
	HandleEvent( &NewEvent);
}
/////////////////////////////////////////////////////////////////////////////
// Function		: SendEvent
// Parameters	: EventID - The Event for listeners to react to.
//					Data - Any data needed to complete the event.
//					Listener - The listener to recieve the event. 
//					Sender - The object who sent the event.
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CEventManager::SendEvent(string EventID, void* Data, void* Listener, void* Sender){
	Event NewEvent(EventID, Sender, Listener, Data);
	m_CurrentEvents.push_back(NewEvent);
}
/////////////////////////////////////////////////////////////////////////////
// Function		: HandleEvent
// Parameters	: pEvent - The Event to handle.
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CEventManager::HandleEvent(Event* pEvent)
{
	pair<multimap<string, CListener*>::iterator, multimap<string, CListener*>::iterator> ClientRange;

	ClientRange = m_Clients.equal_range(pEvent->GetEventIDtype());

	multimap<string, CListener*>::iterator MapIter = ClientRange.first;

	for (MapIter; MapIter != ClientRange.second; MapIter++)
		(*MapIter).second->HandleEvent(pEvent);
}
/////////////////////////////////////////////////////////////////////////////
// Function		: ProcessEvents
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CEventManager::ProcessEvents(){
	while (m_CurrentEvents.size())
	{
		HandleEvent(&m_CurrentEvents.front());
		m_CurrentEvents.pop_front();
	}
}
/////////////////////////////////////////////////////////////////////////////
// Function		: ClearEvents
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CEventManager::ClearEvents(){
	m_CurrentEvents.clear();
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Shutdown
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CEventManager::Shutdown(){
	m_Clients.clear();
	ClearEvents();
}

